﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using BibMan.controller;
using BibMan.model;
using BibMan.model.database;
using BibMan.model.database.Referencer;

namespace BibMan.gui {

    public partial class Front : Form {

        public Front() {
            InitializeComponent();

            Model.Instance.DatabaseLoaded += ResetEvents;
            Model.Instance.DatabaseCreated += ResetEvents;
            Model.Instance.LoadDatabase(Program.filename);
        }

        private void ResetEvents() {
            selectedReferenceIndex = -1;
            selectedPinIndex = -1;
            this.referenceTable1.SelectionChanged -= ReferenceSelectionChanged;
            this.referenceTable1.SelectionChanged += ReferenceSelectionChanged;
            this.referenceTable1.EditRowStarted -= CommitNotes;
            this.referenceTable1.EditRowStarted += CommitNotes;
            this.pinListBox1.SelectedIndexChanged -= PinSelectionChanged;
            this.pinListBox1.SelectedIndexChanged += PinSelectionChanged;
        }

        private int selectedReferenceIndex = -1;
        private void CommitReferenceNotes() {
            if (selectedReferenceIndex >= 0 && selectedReferenceIndex < referenceTable1.Rows.Count) {
                String prev = referenceTable1.Rows[selectedReferenceIndex].Cells["Id"].Value.ToString();
                Model.Instance.Database[prev].Notes = this.notesPanel.ReferenceNotes;
            }
        }

        //Need to remember (or get) previous row selection, and update any changes to it's notes!
        private void ReferenceSelectionChanged(object sender, EventArgs e) {
            CommitReferenceNotes();
            String key = referenceTable1.CurrentRow.Cells["Id"].Value.ToString();
            selectedReferenceIndex = referenceTable1.CurrentRow.Index;
            this.notesPanel.ReferenceNotes = Model.Instance.Database[key].Notes;
        }

        private int selectedPinIndex = -1;
        private void CommitPinNotes() {
            if (selectedPinIndex >= 0 && selectedPinIndex < pinListBox1.Items.Count) {
                String prev = pinListBox1.Items[selectedPinIndex].ToString();
                Model.Instance.Database.Pins[prev].Notes = this.notesPanel.PinNotes;
            }
        }
        private void PinSelectionChanged(object sender, EventArgs e) {
            CommitPinNotes();
            String key = pinListBox1.SelectedItem.ToString();

            DoSearch();

            //todo make a pin for All and Unpinned by default, then this statement can be removed.
            if (Model.Instance.Database.Pins.ContainsKey(key)) {
                selectedPinIndex = pinListBox1.SelectedIndex;
                this.notesPanel.PinNotes = Model.Instance.Database.Pins[key].Notes;
            }
        }

        private void CommitNotes() {
            CommitReferenceNotes();
            CommitPinNotes();
        }

        private void openButtonClicked(object sender, EventArgs e) {
            this.referenceTable1.SelectionChanged -= ReferenceSelectionChanged;
            this.referenceTable1.EditRowStarted -= CommitNotes;
            CommitNotes();
            DialogResult saveResult = MessageBox.Show(this, "Do you want to save the current reference database?", "Save?", MessageBoxButtons.YesNoCancel);
            if (saveResult == DialogResult.OK) {
                saveButtonClicked(sender, e);
            } else if (saveResult == DialogResult.No) {
                this.openXMLFileDialog.FileName = Model.Instance.Filename;
                DialogResult openResult = this.openXMLFileDialog.ShowDialog(this);
                if (openResult == DialogResult.OK) {
                    Model.Instance.LoadDatabase(this.openXMLFileDialog.FileName);
                }
            }            
        }

        private void saveButtonClicked(object sender, EventArgs e) {
            CommitNotes();
            if (Model.Instance.Filename == null) {
                DialogResult result = this.saveXMLFileDialog.ShowDialog();
                if (result == DialogResult.OK) {
                    Model.Instance.Filename = saveXMLFileDialog.FileName;
                } else {
                    return;
                }
            }
            Model.Instance.SaveDatabase(Model.Instance.Filename);
        }

        private void newDatabaseClicked(object sender, EventArgs e) {
            this.referenceTable1.SelectionChanged -= ReferenceSelectionChanged;
            this.referenceTable1.EditRowStarted -= CommitNotes;
            CommitNotes();
            DialogResult result = MessageBox.Show(this, "Do you want to save the current reference database?", "Save?", MessageBoxButtons.YesNoCancel);
            if (result == DialogResult.OK) {
                saveButtonClicked(sender, e);
            } else if (result == DialogResult.No) {
                Model.Instance.NewDatabase();
            }
        }

        private void settingsToolStripButton_Click(object sender, EventArgs e) {
            SettingsForm settings = new SettingsForm();
            DialogResult result = settings.ShowDialog();
            if (result == DialogResult.OK) {
                //enact new settings
                throw new NotImplementedException();
            }
        }

        private void bibTexToolStripButton_Click(object sender, EventArgs e) {
            DialogResult result = saveBibTexFileDialog.ShowDialog();
            if (result == DialogResult.OK) {
                DatabaseLoader.SaveAsBibTex(Model.Instance.Database, saveBibTexFileDialog.FileName);
            }
        }

        private void SearchBoxTextChanged(object sender, EventArgs e) {
            DoSearch();
        }

        private void OnSearchBoxKeyDown(object sender, KeyEventArgs e) {
            if ((e.KeyCode == Keys.Back) && e.Control) {
                SendKeys.SendWait("^+{LEFT}{BACKSPACE}");
            }
        }

        private void DoSearch() {
            String query = toolStripSearchBox.Text;
            
            Searcher searcher = new Searcher(toolStripSearchBox.Text);
            searcher.SearchSet = pinListBox1.References;
            IEnumerable<String> s = searcher.Search();

            if (query.Equals(String.Empty)) {
                this.referenceTable1.UnMasc();
            } else {
                this.referenceTable1.Masc(s);
            }
        }

        private void fromReferencerItem_Click(object sender, EventArgs e) {
            this.referenceTable1.SelectionChanged -= ReferenceSelectionChanged;
            this.referenceTable1.EditRowStarted -= CommitNotes;
            DialogResult saveResult = MessageBox.Show(this, "Do you want to save the current reference database?", "Save?", MessageBoxButtons.YesNoCancel);
            if (saveResult == DialogResult.OK) {
                saveButtonClicked(sender, e);
            } else if (saveResult == DialogResult.No) {
                this.importFromReferencerDialog.FileName = Model.Instance.Filename;
                DialogResult openResult = this.importFromReferencerDialog.ShowDialog(this);
                if (openResult == DialogResult.OK) {
                    JabRefLoader loader = new JabRefLoader(this.importFromReferencerDialog.FileName);
                    Database db = loader.Load().ToDatabase();
                    Model.Instance.NewDatabase();
                    foreach (String key in db.Pins.Keys) {
                        Model.Instance.Database.Pins.Add(key, db.Pins[key]);
                    }
                    foreach (Reference r in db) {
                        Model.Instance.Database.References.Add(r.Id, r);
                    }
                }
            } 
        }

       

       

        


    }
}